package com.xiyue.leaspring.service;

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

import com.xiyue.leaspring.service.annotation.NewEditCache;
import com.xiyue.leaspring.vo.News;



@CacheConfig(cacheNames = "news")//进行该接口缓存的统一配置
public interface INewsService2 {

	/**
	 * 缓存存储注解
	 * 使用@Cacheable注解
	 * 
	 * 进行缓存操作时，所有数据都是以key-value的形式存储的。默认情况下，Spring
	 * 会为每个缓存对象进行命名处理。如果用户有需要，也可以在@Cacheable注解中设
	 * 置缓存的key生成策略。此时程序采用SpEL表达式，直接使用get方法中的nid参数
	 * 作为缓存的名称。如果此时传递参数为一个对象，也可以采用key = "#对象参数.属性"
	 * 形式，使用类中的某一个属性作为缓存名称。
	 * 
	 * 默认情况下，Spring对标注了@Cacheable注解的方法不会进行线程同步管理，
	 * 这样当多个线程同时访问时，就可能造成查询多次的处理问题。为了解决此操作，
	 * 可以采用同步阻塞的方式进行处理，即当有多个线程使用同一参数同时查询时，
	 * Spring的缓存管理器将采用阻塞的形式只发出一次查询处理，
	 * 其他线程将进入到阻塞状态。成功取得数据后，
	 * 所有阻塞的线程将可以直接缓存数据。
	 * 使用sync实现缓存同步处理
	 *
	 * 在进行数据缓存处理时，也可以使用condition属性定义数据被缓存的触发条件，
	 * 此属性可以直接利用SpEL进行条件判断。
	 * 
	 * 默认情况下Spring缓存会针对于配置注解而后进行数据缓存，如果需要设置一些
	 * 不缓存的数据，可以使用unless，在此属性中可以利用SpEL表达式进行判断。如
	 * 为Spring缓存中可以使用的SpEL上下文表达式。
	 * #root.methodName					root对象		当前调用的方法名称
	 * #root.method.name				root对象		当前执行的方法
	 * #root.target						root对象		当前执行的目标对象
	 * #root.targetClass				root对象		当前执行目标对象所属的类
	 * #root.args[0] 或 #root.args[1]	root对象		当前调用参数列表
	 * #root.caches[0].name				root对象		当前方法调用的缓存列表
	 * 
	 * get(Long nid),则为#nid			执行上下文		当前调用方法参数，可以是普通
	 * edit(News vo),则为#vo.nid						参数或者是对象参数
	 * #result (#result,属性表示返回对象属性)执行上下文		方法执行的返回值 
	 * 
	 * 定义缓存排除策略。本程序使用了unless="#result==null"属性，该配置表示：
	 * 结果返回为null时，不再进行数据缓存
	 * 
	 * @Cacheable(sync=true) does not support unless attribute on 'Builder[public com.xiyue.leaspring.vo.News com.xiyue.leaspring.service.impl.MewsServiceImpl.get(java.lang.Long)] caches=[news] | key='#nid' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='#nid>50' | unless='#result==null' | sync='true''
	 * 
	 * @param nid
	 * @return
	 */
//	@Cacheable(cacheNames = "news",key="#nid",sync = true,condition = "#nid>50",
//			unless = "#result==null")//启用缓存，同时定义使用的缓存管理器中的缓存信息名称
//	@Cacheable(cacheNames = "news",key="#nid",sync = true,condition = "#nid>50")
	@Cacheable(key="#nid",unless = "#result==null")
	public News get(Long nid);
	
	/**
	 * 数据更新操作
	 * 
	 * 此时需要进行缓存更新，所以方法上要使用@CachePut注解
	 * 
	 * @param vo 要更新的数据
	 * @return	更新后的数据，主要用于缓存操作
	 */
//	@CachePut(cacheNames = "news",key="#vo.nid",condition = "#vo.nid>0",unless = "#result==null")
//	@CachePut(key="#vo.nid",unless = "#result==null")
//	@Caching(put= {
//			/**
//			 * cacheable	定义多个缓存配置注解
//			 * put			定义多个更新缓存配置注解
//			 * evict		定义多个删除缓存配置注解
//			 * @param vo
//			 * @return
//			 */
//			@CachePut(key="#vo.nid",unless = "#result==null"),
//			@CachePut(key="#vo.title",unless = "#result==null")
//	})
	@NewEditCache
	public News edit(News vo);
	
	/**
	 * 删除新闻数据
	 * 
	 * 删除方法时若要删除缓存使用@CacheEvict
	 * 相关属性
	 * cacheNames			缓存区名称
	 * key					缓存的key,可以使用SpEL编写
	 * condition			缓存删除条件
	 * allEntries			是否清楚全部缓存数据,如果指定为true,则方法调用后将立即清空所有缓存
	 * beforeInvocation		是否在方法执行前就清空,默认指定为false,如果指定为true,则在方法还没有执行的时候就清空缓存，默认情况下,如果方法执行抛出异常,则不会清空缓存
	 * 
	 * @param id 新闻编号
	 * @return 删除成功后返回true,否则返回false
	 */
//	@CacheEvict(cacheNames = "news",key="#nid")
	@CacheEvict(key="#nid")
	public boolean delete(long nid);
	
}
